package cn.dengta.webapp.trade.config;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;

import cn.dengta.common.util.BeanUtil;
import cn.dengta.context.model.WesKit;
import cn.dengta.context.rpc.CachedConfig;
import cn.dengta.context.rpc.CachedConfigManager;
import cn.dengta.webapp.user.model.UserSketch;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import me.codeplayer.util.*;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.InitializingBean;

/**
 * 积分交易（转换）规则配置
 * <p>
 * https://alidocs.dingtalk.com/i/team/apjG5nBqk6dy2zkE/docs/apjG5rb1JB5y4zkE# 「海外产品-货币规则」
 */
@Getter
@Setter
@Slf4j
public class IntegralTradeProperties implements InitializingBean {

	protected Map<WesKit, TradeItem> items;

	/** 积分兑换人民币的除数 D，默认是 10，即 1积分 = 1/10 人民币 */
	protected final transient BigDecimal integralToRMBDivisor = BigDecimal.TEN;
	/** 充值钻石 转 积分的系数 = 0.5 */
	protected final transient BigDecimal coinToIntegralFactor = BigDecimal.valueOf(0.5); // 50% => 2充值钻石 = 1积分
	/** 活动（免费）钻石 转 积分的系数 = 0.05 【固定分成比例，不跟随其他设置系数调整】 */
	protected final transient BigDecimal freeCoinToIntegralFactor = BigDecimal.valueOf(0.05); // 5% => 20活动钻石=2充值钻石=1积分

	static final CachedConfig<IntegralTradeProperties> cache = CachedConfigManager.create("integral_trade", IntegralTradeProperties.class, () -> new IntegralTradeProperties().initDefault());

	public static IntegralTradeProperties get() {
		return cache.get();
	}

	public static CachedConfig<IntegralTradeProperties> cache() {
		return cache;
	}

	public IntegralTradeProperties initDefault() {
		items = new HashMap<>();
		for (WesKit wesKit : WesKit.values()) {
			items.put(wesKit, new TradeItem().initDefault());
		}
		return this;
	}

	/**
	 * 积分兑换人民币（结果保留两位小数）
	 */
	public BigDecimal calcIntegralToRMB(BigDecimal integral) {
		// 积分 / 除数  = 人民币
		return calcIntegralToRMB(integral, integralToRMBDivisor);
	}

	/**
	 * 积分兑换人民币（结果保留两位小数）
	 */
	public BigDecimal calcIntegralToRMB(BigDecimal integral, BigDecimal integralToRMBDivisor) {
		// 积分 / 除数  = 人民币
		return integral.divide(integralToRMBDivisor, 10, RoundingMode.HALF_DOWN);
	}

	/**
	 * 计算提现手续费（结果保留两位小数）
	 */
	public BigDecimal calcCashFee(BigDecimal cash, WesKit wesKit) {
		// 人民币 * 提现手续费速算系数（手续费费率）
		return cash.multiply(this.getCashFeeRate(wesKit)).setScale(2, RoundingMode.HALF_UP);
	}

	/**
	 * 礼物收益因子
	 */
	public BigDecimal calcGiftRate(UserSketch user, WesKit wesKit) {
		return this.getGiftRate(wesKit);
	}

	/**
	 * 计算最终的积分收益
	 *
	 * @param totalCoin 用户消耗的钻石
	 * @param freePart 其中包含的免费钻石数
	 * left: 充值钻收益
	 * right: 免费钻收益
	 */
	public Pair<BigDecimal, BigDecimal> calcFinalIntegralIncome(int totalCoin, int freePart, @Nullable BigDecimal agentIncomeRate, WesKit wesKit) {
		BigDecimal incomeRate = this.getIncomeRate(wesKit);
		BigDecimal factor = agentIncomeRate != null ? agentIncomeRate : incomeRate;
		int real = totalCoin - freePart;
		BigDecimal incomeForReal = real > 0 ? BigDecimal.valueOf(real).multiply(coinToIntegralFactor).multiply(factor) : BigDecimal.ZERO;
		BigDecimal incomeForFree = freePart > 0 ? BigDecimal.valueOf(freePart).multiply(freeCoinToIntegralFactor) : BigDecimal.ZERO;
		//  = ( 充值钻石 * 0.5 ) * 0.35 + ( 活动钻石 * 0.05 )
		return Pair.of(incomeForReal, incomeForFree);
	}

	/** 获取总积分收益 */
	public BigDecimal calcFinalIntegralIncomeTotal(int totalCoin, int freePart, @Nullable BigDecimal agentIncomeRate, WesKit wesKit) {
		return IntegralTradeProperties.calcFinalIntegralIncomeTotal(calcFinalIntegralIncome(totalCoin, freePart, agentIncomeRate, wesKit));
	}

	public static final BigDecimal calcFinalIntegralIncomeTotal(Pair<BigDecimal, BigDecimal> income) {
		return income.getLeft().add(income.getRight()).setScale(2, RoundingMode.HALF_DOWN);
	}

	public BigDecimal cashFeePercentage(WesKit wesKit) {
		return this.getCashFeeRate(wesKit).movePointRight(2);
	}

	public void check() {
		Assert.isTrue(X.isValid(this.items), "请设置参数");
		for (Map.Entry<WesKit, TradeItem> entry : this.items.entrySet()) {
			entry.getValue().check();
		}
	}

	public Map<String, TradeItem> output() {
		Map<String, TradeItem> map = new HashMap<>();
		if (X.isValid(this.items)) {
			for (Map.Entry<WesKit, TradeItem> entry : items.entrySet()) {
				TradeItem trade = new TradeItem();
				BeanUtil.copyProperties(entry.getValue(), trade);
				trade.cashFeeRate = trade.cashFeeRate.movePointRight(2);
				trade.incomeRate = trade.incomeRate.movePointRight(2);
				trade.giftRate = trade.giftRate.movePointRight(2);
				map.put(entry.getKey().name(), trade);
			}
		}
		return map;
	}

	@Override
	public void afterPropertiesSet() {

	}

	public BigDecimal getCashFeeRate(WesKit wesKit) {
		return this.items.get(wesKit).getCashFeeRate();
	}

	public BigDecimal getIncomeRate(WesKit wesKit) {
		return this.items.get(wesKit).getIncomeRate();
	}

	public BigDecimal getGiftRate(WesKit wesKit) {
		return this.items.get(wesKit).getGiftRate();
	}

	@Getter
	@Setter
	public static class TradeItem implements Serializable {

		/** 积分提现手续费率：0% */
		protected BigDecimal cashFeeRate;
		/** 收益方的默认收益比例：默认是 0.28，即 28% （ 钻石转积分，还要额外除以 2 ） */
		protected BigDecimal incomeRate;
		/** 礼物分成：默认：默认是 0.3，即 30% */
		protected BigDecimal giftRate;

		public TradeItem initDefault() {
			cashFeeRate = BigDecimal.ZERO;
			incomeRate = BigDecimal.valueOf(0.28);
			giftRate = BigDecimal.valueOf(0.3);
			return this;
		}

		public void check() {
			Assert.isTrue(cashFeeRate.compareTo(BigDecimal.ZERO) >= 0 && cashFeeRate.compareTo(Arith.HUNDRED) <= 0, "积分提现手续费率 >=0% && <= 100%");
			Assert.isTrue(incomeRate.compareTo(BigDecimal.ZERO) >= 0 && incomeRate.compareTo(Arith.HUNDRED) <= 0, "收益方的默认收益比例 >=0% && <= 100%");
			Assert.isTrue(giftRate.compareTo(BigDecimal.ZERO) >= 0 && giftRate.compareTo(Arith.HUNDRED) <= 0, "礼物分成比例 >=0% && <= 100%");
			this.cashFeeRate = this.cashFeeRate.movePointLeft(2);
			this.incomeRate = this.incomeRate.movePointLeft(2);
			this.giftRate = this.giftRate.movePointLeft(2);
		}

	}

}
